import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.HashMap;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;


public class SpreadToXML
{
	static XMLOutputFactory factory;
	static XMLStreamWriter writer;
	static XMLStreamReader reader;
	static String filename;
	static JTable tableToSave;
	static Boolean containsElement;
	static HashMap<String, String> altNames;
	static String cell, data;
	static SecretKey key;
	
	/**
	 * Traverses the spreadsheet and saves it to an XML file if encryptData is true, a key is set up and is
	 * encrypted using DES encryption in encrypt.java
	 * 
	 * @param table - The table that is brought it to be saved.
	 * @param map - The hash map used to get variable names.
	 * @param encryptData - boolean flag to tell whether or not to encrypt the data.
	 * @param keyIn - the encryption key.
	 * @param filename - the name of the file.
	 * @return Boolean
	 * @throws IOException 
	 * @throws InvalidKeySpecException 
	 */
	public static boolean save(JTable table,HashMap<String,String> map, boolean encryptData, String keyIn, String filename)
	{
		tableToSave = table;
		altNames = map;
		factory = XMLOutputFactory.newInstance();

		try 
		{
			if(encryptData)
				try {
					encrypt.makeSymmetricKey(keyIn);
				} catch (InvalidKeyException e) {return false;} 
				catch (NoSuchAlgorithmException e) {return false;} 
				catch (InvalidKeySpecException e) {return false;}
				
			writer = factory.createXMLStreamWriter(new DataOutputStream(new BufferedOutputStream(new FileOutputStream(filename))));
			writer.writeStartDocument("1.0");

			writer.writeStartElement("spreadsheet");
			writer.writeStartElement("key");

			if(!keyIn.equals("-1")) // added this line *********
				keyIn = encrypt.encryptSecretKey(keyIn);
			writer.writeCharacters(keyIn);
			
			writer.writeEndElement();
			for(int i = 0; i < tableToSave.getRowCount(); i++)
			{
				for(int k = 0; k < tableToSave.getColumnCount(); k++)
				{
					if(tableToSave.getValueAt(i,k) != "")
					{
						containsElement = true;
						break;
					}
					else
					{
						containsElement = false;
					}
				}
				
				if(containsElement)
				{
					writer.writeStartElement("row"); //<row>
					writer.writeAttribute("id", (i+"")); //<row id=i>
					
					for(int j = 0; j < tableToSave.getColumnCount(); j++)
					{
						if(tableToSave.getValueAt(i,j) != "")
						{
							writer.writeStartElement("col"); // <col>
							writer.writeAttribute("id", (j+""));// <col id=j>
							writer.writeStartElement("data");
							data = tableToSave.getValueAt(i,j).toString();
							if(encryptData)
								data = encrypt.encrypter(data);
							writer.writeCharacters(data);
							writer.writeEndElement(); // </data>
							writer.writeStartElement("varName");
			
							cell = tableToSave.getColumnName(j) + i;

							if(altNames.containsKey(cell))
							{
								cell = altNames.get(cell);
								if(encryptData)
									cell = encrypt.encrypter(cell);
								writer.writeCharacters(cell);
							}
							writer.writeEndElement(); // </varName>
							writer.writeEndElement();
						}
					}
					
					writer.writeEndElement(); // </row>
				}
			} // row for loop
			
			writer.writeEndElement(); // </Spreadsheet>
			writer.writeEndDocument();
			writer.flush();
			writer.close();
		} // try
		catch (FileNotFoundException e) 
		{
			JOptionPane.showMessageDialog(null,"Sorry, the file was not found.");
			return false;
		} 
		catch (XMLStreamException e) 
		{
			JOptionPane.showMessageDialog(null,"Sorry, a stream writing error has occured");
			return false;
		} 
		catch (InvalidKeyException e) {System.out.println("InvalidKey");return false;} 
		catch (NoSuchAlgorithmException e) {System.out.println("NoSuchAlgorithmException");return false;} 
		catch (NoSuchPaddingException e) {System.out.println("NoSuchPaddingException");return false;} 
		catch (IllegalBlockSizeException e) {System.out.println("IllegalBlockSizeException");return false;} 
		catch (BadPaddingException e) {System.out.println("BadPaddingException");return false;} 
		catch (UnsupportedEncodingException e) {System.out.println("UnsupportedEncodingException");return false;} 
		catch (InvalidKeySpecException e) {System.out.println("InvalidKeySpecException");return false;} 
		catch (IOException e) {System.out.println("IOException");return false;}
		
		//JOptionPane.showMessageDialog(null,"The file: " + filename + " has been successfully created.");
		return true;
	}
}
